/**
 * request 网络请求工具
 * 更详细的 api 文档: https://github.com/umijs/umi-request
 */
import { extend } from 'umi-request';
import { message } from 'antd';
import { getToken, storageClear, encryptSign } from './utils';
import router from 'umi/router';
import { windowUrl } from '../../public/global';
import { whiteList } from '@/pages/soaManage/abilitymanagement/utils';
import { umiDispatch } from '@/layouts/BasicLayout';
import { generateFingerprint } from './fingerprint';
import { getFingerprint } from './common';

const codeMessage = {
  200: '服务器成功返回请求的数据。',
  201: '新建或修改数据成功。',
  202: '一个请求已经进入后台排队（异步任务）。',
  204: '删除数据成功。',
  400: '发出的请求有错误，服务器没有进行新建或修改数据的操作。',
  401: '用户没有权限（令牌、用户名、密码错误）。',
  403: '用户得到授权，但是访问是被禁止的。',
  404: '发出的请求针对的是不存在的记录，服务器没有进行操作。',
  406: '请求的格式不可得。',
  408: '请求超时。',
  410: '请求的资源被永久删除，且不会再得到的。',
  422: '当创建一个对象时，发生一个验证错误。',
  500: '服务器发生错误，请检查服务器。',
  502: '网关错误。',
  503: '服务不可用，服务器暂时过载或维护。',
  504: '网关超时。',
};
const requestBuffer = extend({
  timeout: 50000,
  responseType: 'arrayBuffer',
});
/**
 * 异常处理程序
 *       服务端返回非2xx都会捕获异常
 */
const errorHandler = (error: { response: Response }) => {
  const { response, name } = error;
  let cloneResponse: object = {};
  if (response) {
    cloneResponse = response.clone();
  }
  if (cloneResponse.status) {
    const errorText = codeMessage[cloneResponse.status] || cloneResponse.statusText;
    const { status } = cloneResponse;
    if (status === 404) {
      router.replace('/Exception/Exception404');
    } else {
      // 判断是不是 check 和 导入
      const regex = /\/(service|skill)\/(importExcel|importExcelCheck)/;

      // 使用test()方法进行匹配，如果匹配成功则返回true，否则返回false
      const isMatched = regex.test(cloneResponse.url);
      if (isMatched) {
        umiDispatch?.({
          type: 'task/updateAllTaskStatus'
        })
      }
      message.error(errorText);
    }
  }
  return cloneResponse;
};

/**
 * 配置request请求时的默认参数
 */
const request = extend({
  errorHandler, // 默认错误处理
  getResponse: false, // 解析response中的data,设置为true不会自动解析
  useCache: false, // 是否使用缓存
  timeout: 50000,
});

//request拦截器, 改变url 或 options.
request.interceptors.request.use(async (url, options) => {
  let fingerprint = await getFingerprint();
  const token = getToken();
  const md5Sign = encryptSign(url, options)
  const optionHeaders: any = options.headers ?? {};
  let tempObj = Object.assign({ 'x-dfiov-fingerprint': fingerprint }, optionHeaders )
  if (md5Sign.length > 0) {
    tempObj.shaSign = md5Sign
  }
  return {
    url: `${windowUrl}${url}`,
    options: {
      ...options,
      headers: token ? { OptAuthorization: `${token}`, ...tempObj } : { ...tempObj },
      interceptors: true,
    },
  };
});

//request拦截器, 改变url 或 options.
requestBuffer.interceptors.request.use(async (url, options) => {
  const token = sessionStorage.getItem('token');
  let fingerprint = await getFingerprint();
  return {
    // url: `${windowUrl}${url}`, // TODO hanzhiming 注释
    options: {
      ...options,
      headers: token
        ? { OptAuthorization: `${token}`, 'x-dfiov-fingerprint': fingerprint, ...options.headers }
        : { ...options.headers },
      interceptors: true,
    },
  };
});
// 克隆响应对象做解析处理
request.interceptors.response.use(async (response) => {
  // 确保响应数据是正确的
  if (response.headers.get('content-type') == 'application/vnd.ms-excel;charset=UTF-8') {
    response.clone().arrayBuffer()
    return response
  }
  if (response.status === 200) {
    const data = await response.clone().json();
    if (data && data.statusCode) {
      if (document.location.hash.startsWith('#/external/') && data.statusCode !== '0') {
        message.error(data.statusMessage);
        return response;
      }

      if (data.statusCode === '9002') {
        const maxCountMessage = message;
        maxCountMessage.config({ maxCount: 1 });
        maxCountMessage.error('登录已失效，请重新登录！');
        storageClear();
        router.replace('/user/login');
      } else if (data.statusCode === '9003') {
        router.replace('/Exception/Exception403');
      } else if (data.statusCode !== '0' ) {
        // 如果业务code在百名单中则不用提示
        if(!whiteList.includes(data.statusCode)){
          message.error(data.statusMessage);
        }
      }
    }
  }
  return response;
});
// 克隆响应对象做解析处理
requestBuffer.interceptors.response.use(async (response) => {
  // 确保响应数据是正确的
  // response.clone().arrayBuffer()
  return response
});
export { requestBuffer }
export default request;

export async function fingerprintFetch(url: string, { headers= {}, ...resetOptions }) {
  let fingerprint = await generateFingerprint();
  return fetch(url, {
    ...resetOptions,
    headers: {
        ...headers,
        'x-dfiov-fingerprint': fingerprint
      }
    }
  );
}